#include "../inc/mzrtos.h"
#include "../inc/mzhw.h"

void _mz_ipc_init(mz_ipc_t ipc){
    mz_list_init(&ipc->suspend_list);
}

#if MZ_USE_MUTEX
void mz_mutex_init(mz_mutex_t mutex,
                   const char* name,
                   mz_uint8_t flag){
    mz_uint32_t level = mz_hw_interrupt_disable();

    mz_object_init(&mutex->parent.parent, name, MZ_OBJECT_MUTEX);

    _mz_ipc_init(&mutex->parent);

    mz_list_init(&mutex->suspend_list);

    mutex->value = 1;
    mutex->parent.parent.flag = flag;

    mz_hw_interrupt_enable(level);
}
void mz_mutex_take(mz_mutex_t mutex){
    mz_thread_t thread;
    mz_uint32_t level;

    thread = mz_thread_self();
    level = mz_hw_interrupt_disable();

    if(mutex->value == 0){
        mz_scheduler_remove_thread(thread);
        if(mutex->parent.parent.flag == MZ_IPC_FLAG_FIFO){
            mz_list_insert_before(&mutex->suspend_list, &thread->list);
        }else{

        }
    }else{
        mutex->value = 0;
    }

    mz_hw_interrupt_enable(level);
}

void mz_mutex_release(mz_mutex_t mutex){
    mz_thread_t thread;
    mz_uint32_t level;

    level = mz_hw_interrupt_disable();
    thread = mz_list_entry(mutex->suspend_list.next,
                           struct mz_thread,
                           list);

    if(thread != MZ_NULL){
        mz_list_remove(&thread->list);
        mz_scheduler_insert_thread(thread);
    }

    mutex->value = 1;

    mz_hw_interrupt_enable(level);
}
#endif